package com.baizhi.shane.config;

import com.baizhi.shane.constant.SysMapping;
import com.baizhi.shane.enums.ResultCode;
import com.baizhi.shane.common.base.Result;
import com.baizhi.shane.sys.enums.SysRoleEnum;
import com.baizhi.shane.sys.manager.RedisManager;
import com.baizhi.shane.sys.service.SysUserService;
import com.baizhi.shane.sys.vo.LoginUserVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.List;

@Slf4j
@Component
public class MyInterceptor implements HandlerInterceptor {

    /**
     * https://blog.csdn.net/hollis_chuang/article/details/112165969
     * 上述博客说明如何在拦截器中注入bean对象
     */
    @Resource
    private RedisManager redisManager;
    @Resource
    private SysUserService sysUserService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        /* 务必放行OPTIONS类型方法，https://blog.csdn.net/Cst_Qiu/article/details/110749113 */
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }
        String url = request.getRequestURI();
        log.info("进入拦截器了");
        log.info("nihao " + url);
        String token = request.getHeader(SysMapping.TOKEN);
//        Object o = redisManager.get("123");
//        log.info(o.toString());


//        // 获取所有的请求头名称
//        Enumeration<String> headerNames = request.getHeaderNames();
//
//        // 遍历请求头名称集合，并打印输出值
//        while (headerNames.hasMoreElements()) {
//            String headerName = headerNames.nextElement();
//            String headerValue = request.getHeader(headerName);
//            System.out.println(headerName + ": " + headerValue);
//        }
//        if (StringUtils.isEmpty(SysMapping.TOKEN)) {
//            try {
//                makeReturn(response);
//            } catch (JSONException e) {
//                throw new RuntimeException(e);
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//
//            return false;
//        }


        boolean isLogin = this.logined(token);
        log.info("isLogin" + isLogin);
        if (!isLogin) {
            try {
                this.makeReturn(response, ResultCode.NO_TOKEN);
            } catch (JSONException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return false;
        }

        /* 如果访问的是后台管理的接口，则需要管理员权限 */
        if (!this.adminCheck(url)) {
            try {
                this.makeReturn(response, ResultCode.NO_ROLE);
            } catch (JSONException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return false;
        }


        //中间写逻辑代码，比如判断是否登录成功，失败则返回false
        return true;
    }

    private boolean adminCheck(String url) {
        /* 如果访问的url并非是管理系统的，那么直接放行就好 */
        if (!url.startsWith(SysMapping.SLASH + SysMapping.SHANE_ADMIN)) {
            return true;
        }
        // 获取管理员的角色英文
        String nameEn = SysRoleEnum.ADMIN.getNameEn();
        /* 获取用户角色列表 */
        LoginUserVO loginUserInfo = this.sysUserService.getLoginUserInfo();
        List<String> roleNameEnList = loginUserInfo.getRoleNameEnList();
        /* 判断admin是否在角色列表中 */
        boolean userIsAdmin = roleNameEnList.contains(nameEn);
        if (userIsAdmin) {
            return true;
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

        // controller执行之后
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 整个请求结束之后
    }
    /**
     * 学习自https://blog.csdn.net/peach90/article/details/77875432
     *
     * @Author 闻柏智
     * @Date 21:42 2023/3/27
     * @Param response
     * @return void
     **/
    private void makeReturn(HttpServletResponse response, ResultCode resultCode) throws JSONException, IOException {
//        String url = "/industryiot/Login.html";
//            response.sendRedirect(url);

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        Result result = Result.fail(resultCode);
        ObjectMapper objectMapper = new ObjectMapper();
        String resultStr = objectMapper.writeValueAsString(result);
        PrintWriter out = null ;
        out = response.getWriter();
        out.write(resultStr);
        out.flush();
        out.close();

    }
    private boolean logined(String token) {
//        RedisTemplate redisTemplate = new RedisTemplate<>();
//        JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
//        connectionFactory.setDatabase(2);
//        redisTemplate.setConnectionFactory(connectionFactory);
//        redisTemplate.afterPropertiesSet();
//        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        Object userIdObj = new Object();
        try {
            userIdObj = redisManager.get(token);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
//            throw new RuntimeException("header里没加Token字段");
            return false;
        }

        /* userIdObj为空，则Token过期 */
        if (userIdObj == null) {
            return false;
        }
        Long userId = (Long) userIdObj;
        if (userId == null) {
            return false;
        }
        // 更新用户的缓存时间为1天
        sysUserService.updateUserLoginCache(token, null, null);
        return true;
    }
}
